/**
 * 扫雷游戏
 * 初级 10个雷 9*9 
 * 中级 40个雷 16*16
 * 高级 99个雷 16*30
 * 
 * 生成一个这样的二维数组
 * [
 *  [0, 0, 0, 0, 0, 0, 0, 1, 9],
 *  [2, 2, 1, 0, 0, 0, 1, 2, 9],
 *  [0, 0, 1, 9, 9, 2, 9, 9, 1]
 * ]
 * 数字9代表的是雷，1，2,3,4代表雷的数量，0代表没有雷
 * 
 */


'use strict'

class Mine {
    constructor(row, col, num) {
        this.row = row;
        this.col = col;
        this.num = num;
        this.dom = document.querySelector('.game-box');
        this.minNum = document.querySelector('.mineNum');
        // 剩余雷的数量
        this.remainNum = this.num;
        // 放二维数组的地图
        this.map = [];
    }
    // 生成一个二维地图
    setMap() {
        // 生成行
        let r = () => {
            for (let i = 0; i < this.row; i++) {
                this.map[i] = new Array();
            };
        }
        let c = () => {
            for (let i = 0; i < this.map.length; i++) {
                for (let j = 0; j < this.col; j++) {
                    this.map[i][j] = 0;
                }
            };
        }
        r();
        c();
    }

    // 地雷放到数组中
    randomMine() {
        let randomM = () => {
            let x = Math.floor(Math.random() * this.row);
            let y = Math.floor(Math.random() * this.col);
            // 随机生成一组坐标，重复就重新生成
            if (this.map[x][y] != 9) {
                this.map[x][y] = 9;
            } else {
                randomM();
            }
        }
        for (let i = 0; i < this.num; i++) {
            randomM();
        }
    }

    // 给地雷周围所有的数字加1
    addNum() {
        let plus = (i, j) => {
            if (i >= 0 && j >= 0 && i < this.row && j < this.col) {
                if (this.map[i][j] !== 9) {
                    this.map[i][j] += 1;
                };
            }
        }
        for (let i = 0; i < this.row; i++) {
            for (let j = 0; j < this.col; j++) {
                if (this.map[i][j] === 9) {
                    // 上下6个数字
                    for (let k = -1; k < 2; k++) {
                        plus(i - 1, j + k);
                        plus(i + 1, j + k);
                    };
                    // 中间两个
                    plus(i, j + 1);
                    plus(i, j - 1);
                }
            }
        }
    }

    // 将雷放到页面dom
    writeHtml() {
        this.dom.innerHTML = '';
        for (let i = 0; i < this.row; i++) {
            this.dom.innerHTML += `<ul class='row x-${i}' data-x='${i}'></ul>`;
        }
        let x = document.querySelectorAll('.row');
        for (let i = 0; i < this.row; i++) {
            for (let j = 0; j < this.col; j++) {
                let m = this.map[i][j];
                x[i].innerHTML += `<li class='col y-${j} num${m}' num='${m}' data-x="${i}" data-y='${j}'></li>`
            }
        };
        // 顺便把雷数量也写到页面
        console.log(this.num, this.remainNum);
        this.minNum.innerHTML = this.num;
    }

    // 扫雷过程
    clearMine(el) {
        let num = el.getAttribute('num');
        if (num != 0) {
            el.innerText = num;
        }
    };

    // 点击显示白色
    diffusion(i, j) {
        if (i < this.row && i >= 0 && j < this.col && j >= 0) {
            let mine = document.querySelector(`.x-${i}`).children[j];
            let num = mine.getAttribute('num');

            // 如果有标记的旗帜，去掉旗帜
            let flag = mine.classList.contains('flag');
            if (flag) {
                mine.classList.toggle('flag');
                this.remainNum++;
                this.minNum.innerHTML = this.remainNum;
            }
            // console.log('扩散颜色', mine.style.backgroundColor);
            if (mine.style.backgroundColor != 'white') {
                if (num <= 9) {
                    mine.style.backgroundColor = 'white';
                    mine.classList.add('hide');
                    // 只有数字是0的时候扩散
                    if (num === '0') {
                        this.showMine(i, j);
                    } else {
                        // 数字不是0则写出数字在页面上
                        mine.innerHTML = num;
                    }
                }
                // console.log('num', num);
                this.isWin();
            };
        }
    };

    // 扩散
    showMine(i, j) {
        this.diffusion(i - 1, j - 1);
        this.diffusion(i - 1, j);
        this.diffusion(i - 1, j + 1);
        this.diffusion(i, j - 1);
        this.diffusion(i, j + 1);
        this.diffusion(i + 1, j - 1);
        this.diffusion(i + 1, j);
        this.diffusion(i + 1, j + 1);
    }

    // 绑定点击事件
    bindClick() {
        let oli = document.querySelectorAll('.row');
        for (let i = 0; i < oli.length; i++) {
            // 左击
            oli[i].addEventListener('click', (e) => {
                let el = e.target;
                let hide = el.classList.contains('hide');
                let flag = el.classList.contains('flag');
                let mine = el.getAttribute('num');
                if (el.tagName == 'LI' && !hide) {
                    if (flag) return;
                    if (mine !== '9' && el.style.backgroundColor !== 'white') {
                        el.style.backgroundColor = 'white';
                        el.classList.add('hide');
                        this.clearMine(el);
                        this.isWin();
                        if (mine === '0') {
                            let x = parseInt(el.dataset.x);
                            let y = parseInt(el.dataset.y);
                            // console.log('给我力量', typeof x, typeof y, x, y);
                            this.showMine(x, y);
                        }
                    } else if (mine === '9') {
                        alert('你输了');
                        // 失败了显示所有地雷
                        let col = document.querySelectorAll('.col');
                        for (let i = 0; i < col.length; i++) {
                            let num = col[i].getAttribute('num');
                            if (num === '9') {
                                col[i].classList.add('boom');
                            }
                        }
                    };
                }
            });

            // 右击
            oli[i].addEventListener('contextmenu', (e) => {
                e.preventDefault();
                let el = e.target;
                if (el.tagName == 'LI') {
                    // 如果标记了10个，就不允许再标记
                    let flag = el.classList.contains('flag');
                    let hide = el.classList.contains('hide');
                    let num = el.getAttribute('num');
                    if (!flag && !hide) {
                        this.remainNum--;
                        if (this.remainNum < 0) {
                            this.remainNum = 0;
                            alert('不能标记地雷了');
                            return;
                        };
                        el.classList.add('flag');
                        if (num === '9') {
                            el.classList.add('flagTrue');
                        }
                    } else {
                        el.classList.remove('flag');
                        el.classList.remove('flagTrue');
                        this.remainNum++;
                        if (this.remainNum >= this.num) {
                            this.remainNum = this.num;
                        }
                    };
                    // console.log('剩余地雷',this.remainNum, this.num);
                    this.minNum.innerHTML = this.remainNum;
                    this.isWin();
                    // console.log(el);
                }

            });
        }


        // 等级按钮绑定点击事件
        var oBtn = document.querySelector('.level');
        oBtn.addEventListener('click', (e) => {
            var el = e.target;
            var classname = el.classList[0];
            switch (classname) {
                case 'primary':
                    this.row = 9;
                    this.col = 9;
                    this.num = 10;
                    this.init();
                    break;
                case 'intermediate':
                    this.row = 16;
                    this.col = 16;
                    this.num = 40;
                    this.init();
                    break;
                case 'advanced':
                    this.row = 16;
                    this.col = 30;
                    this.num = 99;
                    this.init();
                    break;
                case 'restart':
                    this.init();
                    break;
                default:
                    break;
            }
            // console.log(el, classname);
        });

    }

    // 判断是否赢了
    isWin() {
        let hd = document.querySelectorAll('.hide').length;
        let flagTrue = document.querySelectorAll('.flagTrue').length;
        let allNum = this.row * this.col;
        // 2种情况，赢游戏
        // 1. 右击旗帜都是地雷
        // 2. 剩余没点开的数量=地雷总数量
        if (flagTrue == this.num || allNum - hd == this.num) {
            alert('大吉大利, 今晚吃鸡');
        }
    }

    // 入口函数
    init() {
        this.remainNum = this.num;
        this.setMap();
        this.randomMine();
        this.addNum();
        this.writeHtml();
        this.bindClick();
    }
}

let mine = new Mine(9, 9, 10);